package com.xu.ai.model.openai.advisor;

import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.ai.chat.client.ChatClientMessageAggregator;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.CallAdvisor;
import org.springframework.ai.chat.client.advisor.api.CallAdvisorChain;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisor;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisorChain;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.model.ModelOptionsUtils;

import reactor.core.publisher.Flux;

/**
 * 默认日志建议器
 *
 * @author xuguan
 * @since 2025/9/16
 */
public class DefaultLoggerAdvisor implements CallAdvisor, StreamAdvisor {
	private static final Logger log = LoggerFactory.getLogger(DefaultLoggerAdvisor.class);
	public static final Function<ChatClientRequest, String> DEFAULT_REQUEST_TO_STRING = ChatClientRequest::toString;
	public static final Function<ChatResponse, String> DEFAULT_RESPONSE_TO_STRING = ModelOptionsUtils::toJsonStringPrettyPrinter;

	// 非流式
	@Override
	public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
		log.info("BEFORE: {}", DEFAULT_REQUEST_TO_STRING.apply(chatClientRequest));

		ChatClientResponse advisedResponse = callAdvisorChain.nextCall(chatClientRequest);

		log.info("AFTER: {}", DEFAULT_RESPONSE_TO_STRING.apply(advisedResponse.chatResponse()));
		return null;
	}

	// 流式
	@Override
	public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) {
		log.info("BEFORE: {}", DEFAULT_REQUEST_TO_STRING.apply(chatClientRequest));

		Flux<ChatClientResponse> advisedResponse = streamAdvisorChain.nextStream(chatClientRequest);

		return (new ChatClientMessageAggregator()).aggregateChatClientResponse(advisedResponse,
				response -> log.info("AFTER: {}", DEFAULT_RESPONSE_TO_STRING.apply(response.chatResponse())));
	}

	@Override
	public String getName() {
		return this.getClass().getSimpleName();
	}

	@Override
	public int getOrder() {
		return 0;
	}
}
